package controllers

import (
	"backend/models"
	"backend/services"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
)

type GroupControl struct {
	service *services.GroupService
}

type GroupResp struct {
	Name string `json:"name"`
	Desc string `json:"desc"`
	Id   uint   `json:"id"`
}

func NewGroupControl(s *services.GroupService) *GroupControl {
	return &GroupControl{service: s}
}

func (g *GroupControl) Create(c *gin.Context) {
	var m *models.Group
	if err := c.ShouldBindJSON(&m); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	if err := g.service.Create(m); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": GroupResp{
		Name: m.Name,
		Desc: m.Desc,
		Id:   m.ID,
	}, "code": 200, "message": "success"})

}

func (g *GroupControl) Update(c *gin.Context) {
	var m *models.Group
	idvalue, ok := c.Params.Get("id")
	if !ok {
		c.JSON(http.StatusBadRequest, gin.H{"err": "miss id params "})
		return
	}
	id, err := strconv.Atoi(idvalue)
	if err != nil || id < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}

	if err := c.ShouldBindJSON(&m); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	if err := g.service.Update(uint64(id), m); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": GroupResp{
		Id:   m.ID,
		Name: m.Name,
		Desc: m.Desc,
	}, "code": 200, "message": "success"})
}

func (g *GroupControl) Delete(c *gin.Context) {
	idvalue, ok := c.Params.Get("id")
	if !ok {
		c.JSON(http.StatusBadRequest, gin.H{"err": "miss id params "})
		return
	}
	id, err := strconv.Atoi(idvalue)
	if err != nil || id < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	if err := g.service.Delete(uint64(id)); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "success", "code": 200, "data": ""})
}

func (g *GroupControl) GetList(c *gin.Context) {

	pageInfo, err := models.GetPageInfo(c)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}

	name := c.Query("name")
	groups, total, err := g.service.GetList(pageInfo, &models.Group{Name: name})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	groupres := []GroupResp{}
	for _, item := range groups {
		groupres = append(groupres, GroupResp{
			Name: item.Name,
			Desc: item.Desc,
			Id:   item.ID,
		})
	}

	c.JSON(http.StatusOK, gin.H{"code": 200, "message": "success", "data": groupres, "page": pageInfo.Page, "size": pageInfo.Size, "total": total})

}

type UserBindGroupForm struct {
	GroupID uint   `json:"group_id"`
	UserIds []uint `json:"user_ids"`
	Action  string `json:"action"` //bind,ubind
}

type BindRoleForm struct {
	GroupID uint   `json:"group_id"`
	RoleIds []uint `json:"role_ids"`
	Action  string `json:"action"` //bind,ubind
}

func (g *GroupControl) BindUser(c *gin.Context) {
	binduserform := &UserBindGroupForm{}
	if err := c.ShouldBindJSON(binduserform); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	if err := g.service.BindUser(binduserform.GroupID, binduserform.UserIds, binduserform.Action); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "message": "success", "data": ""})
}

func (g *GroupControl) ListBindUser(c *gin.Context) {
	pageinfo, err := models.GetPageInfo(c)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	group_id, err := models.GetParamsInt(c, "id")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	username := c.Query("username")
	email := c.Query("email")
	var query models.User
	query.Username = username
	query.Email = email
	resp, total, err := g.service.ListBindUser(uint(group_id), pageinfo, &query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	userresp := []UserResp{}
	for _, item := range resp {
		userresp = append(userresp, UserResp{
			UserName: item.Username,
			Email:    item.Email,
			Avatar:   item.Avatar,
			Id:       item.ID,
		})
	}
	c.JSON(http.StatusOK, gin.H{"data": userresp, "total": total})
}

func (g *GroupControl) BindRole(c *gin.Context) {
	bindroleform := &BindRoleForm{}
	if err := c.ShouldBindJSON(bindroleform); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	if err := g.service.BindRole(bindroleform.GroupID, bindroleform.RoleIds, bindroleform.Action); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "message": "success", "data": ""})
}

func (g *GroupControl) ListBindRole(c *gin.Context) {
	pageinfo, err := models.GetPageInfo(c)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	group_id, err := models.GetParamsInt(c, "id")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
		return
	}
	name := c.Query("name")

	var query models.Role
	query.Name = name
	resp, total, err := g.service.ListBindRole(uint(group_id), pageinfo, &query)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"err": err.Error()})
		return
	}
	roleresp := []RoleResp{}
	for _, item := range resp {
		roleresp = append(roleresp, RoleResp{
			Name: item.Name,
			Id:   item.ID,
			Desc: item.Desc,
		})
	}
	c.JSON(http.StatusOK, gin.H{"data": roleresp, "total": total})
}
